package com.gitee.shigen.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gitee.shigen.config.SyncConfig;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Date;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

/**
 * @author shigenfu
 * @date 2023/12/26 16:58
 */
@Service
@Slf4j
public class MainService {

    @Resource
    private SyncConfig syncConfig;

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private RestHighLevelClient restHighLevelClient;

    private static final String SQL_LAST_VALUE_IDENTITY = ":sql_last_value";


    public void sync() {
        // 读取文件
        String sqlLastValueFile = syncConfig.getSqlLastValueFile();
        String lastValue = getLastValueFromFile(sqlLastValueFile);

        String sql = syncConfig.getSql();
        sql = StrUtil.replace(sql, SQL_LAST_VALUE_IDENTITY, '"' + lastValue + '"');
        log.info("final sql: {}", sql);

        // 获取结果集
        ResultSet resultSet = getResultSet(sql);
        // 获得tableName将作为索引
        String tableName = getTableName(resultSet);
        log.info("tableName: {}", tableName);

        JSONArray records = getRecords(resultSet);
        System.out.println(records);
        Boolean result = saveOrUpdateJsonToEs(tableName, records);
        log.info("saveOrUpdateJsonToEs result: {}", result);
        if (result) {
            String dateTime = DateUtil.formatDateTime(new Date());
            FileUtil.writeString(dateTime, new File(sqlLastValueFile), StandardCharsets.UTF_8);
        }
    }

    public Connection getConnection() {
        try {
            Connection connection = jdbcTemplate.getDataSource().getConnection();
            return connection;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            throw new RuntimeException("获取数据库连接失败");
        }
    }

    public String getLastValueFromFile(String filePath) {
        File recordFile = new File(filePath);
        if (!FileUtil.exist(recordFile)) {
            FileUtil.touch(recordFile);
        }
        String lastValue = FileUtil.readString(recordFile, StandardCharsets.UTF_8);
        if (StrUtil.isEmpty(lastValue)) {
            lastValue = DateUtil.formatDateTime(DateUtil.date(0));
        } else {
            lastValue = DateUtil.formatDateTime(DateUtil.parse(lastValue));
        }
        return lastValue;
    }


    public ResultSet getResultSet(String sql) {
        Connection connection = getConnection();
        PreparedStatement preparedStatement;
        ResultSet resultSet;
        try {
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery(sql);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            throw new RuntimeException("获取执行结果异常");
        }
        return resultSet;
    }

    public String getTableName(ResultSet resultSet) {
        try {
            return resultSet.getMetaData().getTableName(2);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            throw new RuntimeException("获取表名异常");
        }
    }

    public JSONArray getRecords(ResultSet resultSet) {
        ResultSetMetaData metaData = null;
        try {
            metaData = resultSet.getMetaData();
            // 数据转换成json
            int columnCount = metaData.getColumnCount();
            JSONArray records = new JSONArray();
            while (resultSet.next()) {
                JSONObject record = new JSONObject();
                for (int i = 1; i <= columnCount; i++) {
                    // 获取列名
                    String columnName = metaData.getColumnName(i);
                    Object columnValue = resultSet.getObject(i);
                    record.put(columnName, columnValue);
                }
                records.add(record);
            }
            return records;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            throw new RuntimeException("转换结果失败");
        }
    }


    public boolean saveOrUpdateJsonToEs(String indexName, JSONArray records) {
        if (records.size() == 0) {
            return true;
        }
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");

        for (int i = 0; i < records.size(); i++) {
            bulkRequest.add(new IndexRequest(indexName).id(records.getJSONObject(i).getString("id"))
                .source(records.getJSONObject(i).toJSONString(), XContentType.JSON));
        }
        BulkResponse bulkItemResponses = null;
        try {
            bulkItemResponses = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (bulkItemResponses == null) {
            return false;
        } else {
            // 检查是否有失败
            log.info("bulkItemResponses: {}", bulkItemResponses.buildFailureMessage());
            return !bulkItemResponses.hasFailures();
        }
    }


}
